package gssapiimport ()// RFC 4121, section 4.2.6.1const (// MICTokenFlagSentByAcceptor - this flag indicates the sender is the context acceptor. When not set, it indicates the sender is the context initiatorMICTokenFlagSentByAcceptor = 1 << iota// MICTokenFlagSealed - this flag indicates confidentiality is provided for. It SHALL NOT be set in MIC tokensMICTokenFlagSealed// MICTokenFlagAcceptorSubkey - a subkey asserted by the context acceptor is used to protect the messageMICTokenFlagAcceptorSubkey)const ( micHdrLen = 16// Length of the MIC Token's header)// MICToken represents a GSS API MIC token, as defined in RFC 4121.// It contains the header fields, the payload (this is not transmitted) and// the checksum, and provides the logic for converting to/from bytes plus// computing and verifying checksumstypeMICTokenstruct {// const GSS Token ID: 0x0404 Flags byte// contains three flags: acceptor, sealed, acceptor subkey// const Filler: 0xFF 0xFF 0xFF 0xFF 0xFF SndSeqNum uint64// sender's sequence number. big-endian Payload []byte// your data! :) Checksum []byte// checksum of { payload | header }}// Return the 2 bytes identifying a GSS API MIC tokenfunc getGSSMICTokenID() *[2]byte {return &[2]byte{0x04, 0x04}}// Return the filler bytes used in headerfunc fillerBytes() *[5]byte {return &[5]byte{0xFF, 0xFF, 0xFF, 0xFF, 0xFF}}// Marshal the MICToken into a byte slice.// The payload should have been set and the checksum computed, otherwise an error is returned.func ( *MICToken) () ([]byte, error) {if .Checksum == nil {returnnil, errors.New("checksum has not been set") } := make([]byte, micHdrLen+len(.Checksum))copy([0:micHdrLen], .getMICChecksumHeader()[:])copy([micHdrLen:], .Checksum)return , nil}// SetChecksum uses the passed encryption key and key usage to compute the checksum over the payload and// the header, and sets the Checksum field of this MICToken.// If the payload has not been set or the checksum has already been set, an error is returned.func ( *MICToken) ( types.EncryptionKey, uint32) error {if .Checksum != nil {returnerrors.New("checksum has already been computed") } , := .checksum(, )if != nil {return } .Checksum = returnnil}// Compute and return the checksum of this token, computed using the passed key and key usage.// Note: This will NOT update the struct's Checksum field.func ( *MICToken) ( types.EncryptionKey, uint32) ([]byte, error) {if .Payload == nil {returnnil, errors.New("cannot compute checksum with uninitialized payload") } := make([]byte, micHdrLen+len(.Payload))copy([0:], .Payload)copy([len(.Payload):], .getMICChecksumHeader()) , := crypto.GetEtype(.KeyType)if != nil {returnnil, }return .GetChecksumHash(.KeyValue, , )}// Build a header suitable for a checksum computationfunc ( *MICToken) () []byte { := make([]byte, micHdrLen)copy([0:2], getGSSMICTokenID()[:]) [2] = .Flagscopy([3:8], fillerBytes()[:])binary.BigEndian.PutUint64([8:16], .SndSeqNum)return}// Verify computes the token's checksum with the provided key and usage,// and compares it to the checksum present in the token.// In case of any failure, (false, err) is returned, with err an explanatory error.func ( *MICToken) ( types.EncryptionKey, uint32) (bool, error) { , := .checksum(, )if != nil {returnfalse, }if !hmac.Equal(, .Checksum) {returnfalse, fmt.Errorf("checksum mismatch. Computed: %s, Contained in token: %s",hex.EncodeToString(), hex.EncodeToString(.Checksum)) }returntrue, nil}// Unmarshal bytes into the corresponding MICToken.// If expectFromAcceptor is true we expect the token to have been emitted by the gss acceptor,// and will check the according flag, returning an error if the token does not match the expectation.func ( *MICToken) ( []byte, bool) error {iflen() < micHdrLen {returnerrors.New("bytes shorter than header length") }if !bytes.Equal(getGSSMICTokenID()[:], [0:2]) {returnfmt.Errorf("wrong Token ID, Expected %s, was %s",hex.EncodeToString(getGSSMICTokenID()[:]),hex.EncodeToString([0:2])) } := [2] := &MICTokenFlagSentByAcceptor != 0if && ! {returnerrors.New("unexpected acceptor flag is set: not expecting a token from the acceptor") }if ! && {returnerrors.New("unexpected acceptor flag is not set: expecting a token from the acceptor, not in the initiator") }if !bytes.Equal([3:8], fillerBytes()[:]) {returnfmt.Errorf("unexpected filler bytes: expecting %s, was %s",hex.EncodeToString(fillerBytes()[:]),hex.EncodeToString([3:8])) } .Flags = .SndSeqNum = binary.BigEndian.Uint64([8:16]) .Checksum = [micHdrLen:]returnnil}// NewInitiatorMICToken builds a new initiator token (acceptor flag will be set to 0) and computes the authenticated checksum.// Other flags are set to 0.// Note that in certain circumstances you may need to provide a sequence number that has been defined earlier.// This is currently not supported.func ( []byte, types.EncryptionKey) (*MICToken, error) { := MICToken{Flags: 0x00,SndSeqNum: 0,Payload: , }if := .SetChecksum(, keyusage.GSSAPI_INITIATOR_SIGN); != nil {returnnil, }return &, nil}
The pages are generated with Goldsv0.6.7. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds.